import React, { useState, useEffect, useRef } from 'react';
import { TextField, Box, Dialog, Button, DialogTitle, DialogContent, DialogContentText, DialogActions, BottomNavigation, BottomNavigationAction, MenuItem } from '@mui/material';
import { Icon } from '@mui/material';
import Utils from '../../../utils/Utils';
import NetPyNEField from '../../general/NetPyNEField';
import NetPyNETextField from '../../general/NetPyNETextField';
import NetPyNESelectField from '../../general/NetPyNESelectField';
import ListComponent from '../../general/List';
import Select from '../../general/Select';
import NetPyNECoordsRange from '../../general/NetPyNECoordsRange';

interface NetPyNESubcellsConnectivityRuleProps {
  name: string;
  model?: Record<string, any>;
  selectPage?: (page: string) => void;
  renameHandler?: (newName: string) => boolean;
  [key: string]: any;
}

/**
 * NetPyNESubcellsConnectivityRule Component
 * Component for editing a single subcell connectivity rule
 * Supports density types (2DMap, 1DMap, distance) with dynamic field rendering
 */
const NetPyNESubcellsConnectivityRule: React.FC<NetPyNESubcellsConnectivityRuleProps> = ({
  name,
  model: propModel,
  selectPage,
  renameHandler,
  ...otherProps
}) => {
  const [currentName, setCurrentName] = useState(name);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const [sectionId, setSectionId] = useState<string>('General');
  const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);
  const [errorDetails, setErrorDetails] = useState<string | undefined>(undefined);
  const [type, setType] = useState<string | undefined>(undefined);
  const [density, setDensity] = useState<any>(undefined);
  const [coord, setCoord] = useState<string | undefined>(undefined);
  const renamingRef = useRef(false);
  const updateTimerRef = useRef<NodeJS.Timeout | undefined>(undefined);

  useEffect(() => {
    refreshComponent();
  }, []);

  useEffect(() => {
    if (currentName !== name) {
      setCurrentName(name);
    }
  }, [name]);

  useEffect(() => {
    if (propModel && JSON.stringify(propModel) !== JSON.stringify(density)) {
      refreshComponent();
    }
  }, [propModel]);

  const refreshComponent = async (): Promise<void> => {
    try {
      const response = await Utils.evalPythonMessage(
        `netpyne_geppetto.netParams.subConnParams["${name}"]`,
        []
      );
      if (typeof response === 'object' && response.density) {
        setType(response.density.type);
        setDensity(response.density);
      }
    } catch (error) {
      console.error('Error refreshing component:', error);
    }
  };

  const handleRenameChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
    const storedValue = name;
    const newValue = Utils.nameValidation(event.target.value);

    if (renameHandler) {
      const updateCondition = renameHandler(newValue);
      const triggerCondition = Utils.handleUpdate(
        updateCondition,
        newValue,
        event.target.value,
        {
          setState: (updater: any) => {
            if (typeof updater === 'function') {
              // Handle function updater if needed
            } else {
              setErrorMessage(updater.errorMessage);
              setErrorDetails(updater.errorDetails);
            }
          },
        },
        'ConnectionRule'
      );

      if (triggerCondition) {
        triggerUpdate(() => {
          Utils.renameKey(
            'netParams.subConnParams',
            storedValue,
            newValue,
            (response: any, newVal: string) => {
              renamingRef.current = false;
            }
          );
          renamingRef.current = true;
        });
      }
    }
  };

  const triggerUpdate = (updateMethod: () => void): void => {
    if (updateTimerRef.current !== undefined) {
      clearTimeout(updateTimerRef.current);
    }
    updateTimerRef.current = setTimeout(updateMethod, 1000);
  };

  const select = (index: number, sectionIdValue: string): void => {
    setSelectedIndex(index);
    setSectionId(sectionIdValue);
  };

  const postProcessMenuItems = (pythonData: string[], selected: string[]): React.ReactNode[] => {
    return pythonData.map((name) => (
      <MenuItem
        id={`${name}MenuItem`}
        key={name}
        value={name}
        selected={selected.indexOf(name) > -1}
      >
        {name}
      </MenuItem>
    ));
  };

  const postProcessDensity = (pythonData: string[], selected: string | string[]): React.ReactNode[] => {
    // Handle the case where pythonData might be an array or a string
    const selectedValue = Array.isArray(selected) ? selected[selected.length - 1] : selected;
    if (typeof selectedValue === 'string') {
      handleDensity(selectedValue);
    } else if (Array.isArray(selected) && selected.length > 0) {
      handleDensity(selected[selected.length - 1]);
    }
    return pythonData.map((name) => (
      <MenuItem
        id={`${name}MenuItem`}
        key={name}
        value={name}
        selected={Array.isArray(selected) ? selected.indexOf(name) > -1 : selected === name}
      >
        {name}
      </MenuItem>
    ));
  };

  const handleDensity = (value: string): void => {
    setType(value);
    Utils.execPythonMessage(
      `netpyne_geppetto.netParams.subConnParams['${name}']['density'] = { 'type': '${value}' }`
    );
  };

  const handleCoord = (value: string): void => {
    setCoord(value);
    if (value === 'cartesian') {
      Utils.execPythonMessage(
        `netpyne_geppetto.netParams.subConnParams['${name}']['density']['coord'] = '${value}'`
      );
      Utils.execPythonMessage('netpyne_geppetto.netParams.defineCellShapes = True');
    } else {
      Utils.execPythonMessage('netpyne_geppetto.netParams.defineCellShapes = False');
      Utils.execPythonMessage(
        `del netpyne_geppetto.netParams.subConnParams['${name}']['density']['coord']`
      );
    }
  };

  const densityExtraFun = (): React.ReactNode => {
    switch (type) {
      case '2DMap':
      case '1DMap':
        Utils.execPythonMessage('netpyne_geppetto.netParams.defineCellShapes = True');
        return (
          <>
            <NetPyNEField id="netParams.subConnParams.density.gridY" className="listStyle">
              <ListComponent
                model={`netParams.subConnParams['${name}']['density']['gridY']`}
              />
            </NetPyNEField>
            {type === '2DMap' && (
              <NetPyNEField id="netParams.subConnParams.density.gridX" className="listStyle">
                <ListComponent
                  model={`netParams.subConnParams['${name}']['density']['gridX']`}
                />
              </NetPyNEField>
            )}
            <NetPyNEField id="netParams.subConnParams.density.fixedSomaY" className="listStyle">
              <ListComponent
                model={`netParams.subConnParams['${name}']['density']['fixedSomaY']`}
              />
            </NetPyNEField>
            <NetPyNEField id="netParams.subConnParams.density.gridValues" className="listStyle">
              <ListComponent
                model={`netParams.subConnParams['${name}']['density']['gridValues']`}
              />
            </NetPyNEField>
          </>
        );
      case 'distance':
        Utils.execPythonMessage('netpyne_geppetto.netParams.defineCellShapes = False');
        return (
          <>
            <NetPyNEField id="netParams.subConnParams.density.ref_sec">
              <NetPyNETextField
                fullWidth
                variant="filled"
                model={`netParams.subConnParams['${name}']['density']['ref_sec']`}
              />
            </NetPyNEField>
            <NetPyNEField id="netParams.subConnParams.density.ref_seg">
              <NetPyNETextField
                fullWidth
                variant="filled"
                model={`netParams.subConnParams['${name}']['density']['ref_seg']`}
              />
            </NetPyNEField>
            <NetPyNEField id="netParams.subConnParams.density.target_distance">
              <NetPyNETextField
                fullWidth
                variant="filled"
                model={`netParams.subConnParams['${name}']['density']['target_distance']`}
              />
            </NetPyNEField>
            <NetPyNEField id="netParams.subConnParams.density.coord">
              <Select
                onChange={(event: any, child: React.ReactNode) =>
                  handleCoord(event.target.value as string)
                }
                value={coord || ''}
                fullWidth
              >
                {['', 'cartesian'].map((name) => (
                  <MenuItem id={`${name}MenuItem`} key={`_${name}`} value={name}>
                    {name}
                  </MenuItem>
                ))}
              </Select>
            </NetPyNEField>
          </>
        );
      default:
        Utils.execPythonMessage('netpyne_geppetto.netParams.defineCellShapes = False');
        return null;
    }
  };

  const dialogPop = errorMessage !== undefined ? (
    <Dialog open style={{ whiteSpace: 'pre-wrap' }}>
      <DialogTitle id="alert-dialog-title">{errorMessage}</DialogTitle>
      <DialogContent style={{ overflow: 'auto' }}>
        <DialogContentText id="alert-dialog-description">
          {errorDetails}
        </DialogContentText>
      </DialogContent>
      <DialogActions>
        <Button
          variant="contained"
          color="primary"
          onClick={() => {
            setErrorMessage(undefined);
            setErrorDetails(undefined);
          }}
        >
          BACK
        </Button>
      </DialogActions>
    </Dialog>
  ) : null;

  const densityExtras = densityExtraFun();
  let content: React.ReactNode = null;

  if (sectionId === 'General') {
    content = (
      <Box className="scrollbar scrollchild" mt={1}>
        <Box mb={1}>
          <TextField
            fullWidth
            variant="filled"
            id="ConnectivityName"
            onChange={handleRenameChange}
            value={currentName}
            disabled={renamingRef.current}
            label="The name of the connectivity rule"
          />
        </Box>

        <NetPyNEField id="netParams.subConnParams.groupSynMechs">
          <NetPyNESelectField
            multiple={true}
            model={`netParams.subConnParams['${name}']['groupSynMechs']`}
            fullWidth
            method="netpyne_geppetto.getAvailableSynMech"
            postProcessItems={(pythonData: string[], selected: string | string[]) =>
              pythonData.map((name) => (
                <MenuItem id={`${name}MenuItem`} key={name} value={name}>
                  {name}
                </MenuItem>
              ))
            }
          />
        </NetPyNEField>

        <NetPyNEField id="netParams.subConnParams.sec" className="listStyle">
          <ListComponent model={`netParams.subConnParams['${name}']['sec']`} />
        </NetPyNEField>

        <NetPyNEField id="netParams.subConnParams.density.type">
          <NetPyNESelectField
            multiple={true}
            fullWidth
            method="netpyne_geppetto.getAvailableDensityTypes"
            model={`netParams.subConnParams['${name}']['density']['type']`}
            postProcessItems={postProcessDensity}
          />
        </NetPyNEField>

        {densityExtras}

        {dialogPop}
      </Box>
    );
  } else if (sectionId === 'Pre Conditions') {
    content = (
      <Box className="scrollbar scrollchild" mt={1}>
        <NetPyNEField id="netParams.subConnParams.preConds.pop">
          <NetPyNESelectField
            model={`netParams.subConnParams['${name}']['preConds']['pop']`}
            method="netpyne_geppetto.getAvailablePops"
            postProcessItems={postProcessMenuItems}
            multiple
          />
        </NetPyNEField>

        <NetPyNEField id="netParams.subConnParams.preConds.cellType">
          <NetPyNESelectField
            fullWidth
            model={`netParams.subConnParams['${name}']['preConds']['cellType']`}
            method="netpyne_geppetto.getAvailableCellTypes"
            postProcessItems={postProcessMenuItems}
            multiple
          />
        </NetPyNEField>

        <NetPyNECoordsRange
          id="xRangePreConn"
          name={name}
          model="netParams.subConnParams"
          conds="preConds"
          items={[
            {
              value: 'x',
              label: 'Absolute',
            },
            {
              value: 'xnorm',
              label: 'Normalized',
            },
          ]}
        />

        <NetPyNECoordsRange
          id="yRangePreConn"
          name={name}
          model="netParams.subConnParams"
          conds="preConds"
          items={[
            {
              value: 'y',
              label: 'Absolute',
            },
            {
              value: 'ynorm',
              label: 'Normalized',
            },
          ]}
        />

        <NetPyNECoordsRange
          id="zRangePreConn"
          name={name}
          model="netParams.subConnParams"
          conds="preConds"
          items={[
            {
              value: 'z',
              label: 'Absolute',
            },
            {
              value: 'znorm',
              label: 'Normalized',
            },
          ]}
        />
      </Box>
    );
  } else if (sectionId === 'Post Conditions') {
    content = (
      <Box className="scrollbar scrollchild" mt={1}>
        <NetPyNEField id="netParams.subConnParams.postConds.pop">
          <NetPyNESelectField
            model={`netParams.subConnParams['${name}']['postConds']['pop']`}
            fullWidth
            method="netpyne_geppetto.getAvailablePops"
            postProcessItems={postProcessMenuItems}
            multiple
          />
        </NetPyNEField>

        <NetPyNEField id="netParams.subConnParams.postConds.cellType">
          <NetPyNESelectField
            model={`netParams.subConnParams['${name}']['postConds']['cellType']`}
            method="netpyne_geppetto.getAvailableCellTypes"
            postProcessItems={postProcessMenuItems}
            multiple
            fullWidth
          />
        </NetPyNEField>

        <NetPyNECoordsRange
          id="xRangePostConn"
          name={name}
          model="netParams.subConnParams"
          conds="postConds"
          items={[
            {
              value: 'x',
              label: 'Absolute',
            },
            {
              value: 'xnorm',
              label: 'Normalized',
            },
          ]}
        />

        <NetPyNECoordsRange
          id="yRangePostConn"
          name={name}
          model="netParams.subConnParams"
          conds="postConds"
          items={[
            {
              value: 'y',
              label: 'Absolute',
            },
            {
              value: 'ynorm',
              label: 'Normalized',
            },
          ]}
        />

        <NetPyNECoordsRange
          id="zRangePostConn"
          name={name}
          model="netParams.subConnParams"
          conds="postConds"
          items={[
            {
              value: 'z',
              label: 'Absolute',
            },
            {
              value: 'znorm',
              label: 'Normalized',
            },
          ]}
        />
      </Box>
    );
  }

  return (
    <div className="layoutVerticalFitInner">
      <BottomNavigation showLabels value={selectedIndex}>
        <BottomNavigationAction
          id="generalConnTab"
          key="General"
          label="General"
          icon={<Icon className="fa fa-bars" />}
          onClick={() => select(0, 'General')}
        />
        <BottomNavigationAction
          id="preCondsConnTab"
          key="Pre Conditions"
          label="Pre-synaptic cells conditions"
          icon={<Icon className="fa fa-caret-square-o-left" />}
          onClick={() => select(1, 'Pre Conditions')}
        />
        <BottomNavigationAction
          id="postCondsConnTab"
          key="Post Conditions"
          label="Post-synaptic cells conditions"
          icon={<Icon className="fa fa-caret-square-o-right" />}
          onClick={() => select(2, 'Post Conditions')}
        />
      </BottomNavigation>
      {content}
    </div>
  );
};

export default NetPyNESubcellsConnectivityRule;

